import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.*;
import java.util.AbstractCollection;
/**
 * The class for patients in the doctor's system. 
 * @author Michael Zipp
 * @version 1.0
 */

public class Patient extends User {
	MedicalRecord medHistory;

	private AbstractCollection<Appointment> appointments;
	
	private String insuranceCarrier;
	
	private String allergies;
	
	private static Logger patientLog = Logger.getLogger(Patient.class.getName());
	
	static{
		ConsoleHandler console = new ConsoleHandler();
		console.setLevel(Level.FINEST);
		console.setFormatter(new ThunderDragonHtmlFormatter());
		patientLog.addHandler(console);
		patientLog.setLevel(Level.ALL);
		
		try {
			FileHandler fh = new FileHandler("PatientLog.txt");
			fh.setFormatter(new ThunderDragonHtmlFormatter());
			patientLog.addHandler(fh);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			patientLog.severe("Failure: Security exception thrown" +
					" when trying to create a new handler" +
					" in Patient.java.");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			patientLog.severe("Failure: I/O exception thrown " +
					"when trying to create a new handler" +
					" in Patient.java.");
			e.printStackTrace();
		}
		
	}

	/**
	 * Creates a new patient for the medical system
	 * @param name Name of the patient
	 * @param username Username for the patients account
	 * @param password Password for the patients account
	 * @param address Patients full address
	 * @param phoneNum Patients phone number
	 * @param email Patients email address
	 * @param age patients age
	 * @param insuranceCarrier Patients insurance carrier
	 * @param allergies Any allergies the patient may have
	 */
	public Patient(String name, String username, String password,
			String address, String phoneNum, String email, String age,
			String insuranceCarrier, String allergies) {
		super(name, username, password, address, phoneNum, email, age);
		patientLog.entering(this.getClass().getName(), 
				"Patient Constructor", new Object[] {name, username,
			password, address, phoneNum, email, age, insuranceCarrier, allergies});
		
		usertype = "patient";
		medHistory = new MedicalRecord(this);
		appointments = new ArrayList<Appointment>();
		this.insuranceCarrier = insuranceCarrier;
		this.allergies = allergies;
		patientLog.exiting(this.getClass().getName(), "Patient Constructor");
	}
	
	public Patient(){
		//super();
		usertype = "patient";
		patientLog.entering(this.getClass().getName(), "Patient Default Constructor");
		patientLog.exiting(this.getClass().getName(), "Patient Default Constructor");
	}
	
	public Patient(User user){
		name = user.name;
		username = user.username;
		password = user.password;
		address = user.address;
		phoneNum = user.phoneNum;
		email = user.email;
		age = user.age;
		usertype = "patient";
	}
	
	public Patient viewUser(){
		patientLog.finest("Called viewUser() in class Patient.");
		return this;
	}
	
	/**
	 * Edit the patients data to match the input
	 * @param a
	 */
	public void editPatient(Patient a){
		editUser(a);
		insuranceCarrier = a.insuranceCarrier;
		allergies = a.allergies;
		patientLog.finest("Called editPatient() in class Patient.");
	}
	
	/**
	 * Adds a new appointment to the patients list of appointments
	 * @param a Appointment to be added
	 */
	public void makeAppointment(Appointment a){
		appointments.add(a);
		patientLog.finest("Called makeAppointment() in class Patient.");
	}
	
	/**
	 * Checks if there is any appointment for the patient that has not yet occurred.
	 * @return How many appointments the patient has
	 */
	
	//Matt's comment: You sure we don't want to make this a boolean?  We can use this to see
	//if our patient has appointments, yes or no.  The appointments that have been confirmed
	//can be popped or removed at some other point in time.
	public int hasAppointment(){
		int counter = 0;
		for (Appointment a : appointments){
			if(!a.hasOccurred()) counter++;
		}
		patientLog.finest("Called hasAppointment() in class Patient.");
		return counter;
	}
	
	/**
	 * Returns the ArrayList of appointments to be displayed by another class.
	 * @return appointments The list of appointments a patient has.
	 */
	public ArrayList<Appointment> viewAppointments(){
		patientLog.finest("Called viewAppointments() in class Patient.");
		return (ArrayList<Appointment>) appointments;
	}
	
	/**
	 * Returns the Medical Record of a patient to be displayed by another class.
	 * @return the Medical Record representing the history
	 */
	public MedicalRecord viewHistory(){
		patientLog.finest("Called viewHistory() in class Patient.");
		return medHistory;
	}

	/**
	 * @return the insuranceCarrier
	 */
	public String getInsuranceCarrier() {
		patientLog.finest("Called getInsuranceCarrier() in class Patient.");
		return insuranceCarrier;
	}

	/**
	 * @param insuranceCarrier the insuranceCarrier to set
	 */
	public void setInsuranceCarrier(String insuranceCarrier) {
		this.insuranceCarrier = insuranceCarrier;
		patientLog.finest("Called setInsuranceCarrier() in class Patient.");
	}

	/**
	 * @return the allergies
	 */
	public String getAllergies() {
		patientLog.finest("Called getAllergies() in class Patient.");
		return allergies;
	}

	/**
	 * @param allergies the allergies to set
	 */
	public void setAllergies(String allergies) {
		this.allergies = allergies;
		patientLog.finest("Called setAllergies() in class Patient.");
	}

	@Override
	public String toString() {
		return "Patient";
	}
	
}